﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Text;
using Jb.Web.ViewModels;
using Jb.Common.Extensions;

namespace Jb.Web.Utility
{
    public static class HtmlHelpers
    {
        /// <summary>
        /// Custom helper method that renders a Warning Message Box based on BootStrap alert
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static MvcHtmlString WarningMessageBox(this HtmlHelper helper, String message, String heading = null)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<div class=\"alert alert-block\">");
            sb.Append("<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>");
            sb.AppendFormat("<h4>{0}</h4>", heading.IsNullOrEmpty() ? "Warning!" : heading);
            sb.AppendFormat(message);                  
            sb.Append("</div>");
            return MvcHtmlString.Create(sb.ToString());
        }

        /// <summary>
        /// Custom helper method that renders a Error Message Box based on BootStrap alert
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static MvcHtmlString ErrorMessageBox(this HtmlHelper helper, string message, String heading = null)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<div class=\"alert alert-error\">");
            sb.Append("<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>");
            sb.AppendFormat("<h4>{0}</h4>", heading.IsNullOrEmpty() ? "Error!" : heading);
            sb.AppendFormat(message);
            sb.Append("</div>");
            return MvcHtmlString.Create(sb.ToString());
        }

        /// <summary>
        /// Custom helper method that renders a Success Message Box based on BootStrap alert
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static MvcHtmlString SuccessMessageBox(this HtmlHelper helper, string message, String heading = null)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<div class=\"alert alert-success\">");
            sb.Append("<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>");
            sb.AppendFormat("<h4>{0}</h4>", heading.IsNullOrEmpty() ? "Success!" : heading);
            sb.AppendFormat(message);
            sb.Append("</div>");
            return MvcHtmlString.Create(sb.ToString());
        }

        /// <summary>
        /// Custom helper method that renders a Info Message Box based on BootStrap alert
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static MvcHtmlString InfoMessageBox(this HtmlHelper helper, string message, String heading = null)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<div class=\"alert alert-info\">");
            sb.Append("<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>");
            sb.AppendFormat("<h4>{0}</h4>", heading.IsNullOrEmpty() ? "Success!" : heading);
            sb.AppendFormat(message);
            sb.Append("</div>");
            return MvcHtmlString.Create(sb.ToString());    
        }

        /// <summary>
        /// Gets Formatted Page Title
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="title"></param>
        /// <returns></returns>
        public static String GetPageTitle(this HtmlHelper helper, string title)
        {
            //return string.Format(".:JobBoard:. {0}", title);
            return String.Format("{0} - {1}", title, ConfigReader.SiteName);
        }

        /// <summary>
        /// Creates a Script Tag for Java Script file
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="scriptName"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public static MvcHtmlString JavaScript(this HtmlHelper helper, string scriptName, UrlHelper url)
        {
            String scriptPath = url.Content(String.Format("~/Scripts/{0}", scriptName));
            return MvcHtmlString.Create(String.Format("<script src=\"{0}\" type=\"text/javascript\"></script>", scriptPath));
        }
        
        /// <summary>
        /// Creates an Action Link tag <a></a> for Administrator Area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="linkText"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static MvcHtmlString AdminLink(this HtmlHelper helper, String linkText, String action, String controllerName, object htmlAttributes = null)
        {
            return helper.ActionLink(linkText, action, controllerName, new { area = AppConstants.Area.ADMIN }, htmlAttributes);
        }
        /// <summary>
        /// Creates an Action Link tag <a></a> for Private Area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="linkText"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static MvcHtmlString PrivateLink(this HtmlHelper helper, String linkText, String action, String controllerName, object htmlAttributes = null)
        {            
            return helper.ActionLink(linkText, action, controllerName, new { area = AppConstants.Area.PRIVATE }, htmlAttributes);
        }
        /// <summary>
        /// Creates an Action Link tag <a></a> for JobSeeker Area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="linkText"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static MvcHtmlString JobSeekerLink(this HtmlHelper helper, String linkText, String action, String controllerName, object htmlAttributes = null)
        {
            return helper.ActionLink(linkText, action, controllerName, new { area = AppConstants.Area.JOB_SEEKER }, htmlAttributes);
        }
        /// <summary>
        /// Creates an Action Link for Public Area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="linkText"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static MvcHtmlString PublicLink(this HtmlHelper helper, String linkText, String action, String controllerName, object htmlAttributes = null)
        {
            return helper.ActionLink(linkText, action, controllerName, new { area = AppConstants.Area.PUBLIC }, htmlAttributes);
        }
        /// <summary>
        /// Creates a relative URL for Private area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static String PrivateUrl(this UrlHelper helper, String action, String controllerName)
        {
            return helper.Action(action, controllerName, new { area = AppConstants.Area.PRIVATE });
        }

        /// <summary>
        /// Creates a relative URL for JobSeeker area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static String JobSeekerUrl(this UrlHelper helper, String action, String controllerName)
        {
            return helper.Action(action, controllerName, new { area = AppConstants.Area.JOB_SEEKER });
        }

        /// <summary>
        /// Creates a relative URL for Admin area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static String AdminUrl(this UrlHelper helper, String action, String controllerName)
        {
            return helper.Action(action, controllerName, new { area = AppConstants.Area.ADMIN });
        }
        /// <summary>
        /// Creates a relative URL for Public area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static String PublicUrl(this UrlHelper helper, String action, String controllerName)
        {
            return helper.Action(action, controllerName, new { area = AppConstants.Area.PUBLIC });
        }

        /// <summary>
        /// Builds the icon URL based on document type
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static String GetFileTypeIconUrl(this UrlHelper helper, String fileName)
        {
            String extension = System.IO.Path.GetExtension(fileName);
            String icon = "txt-icon.png";
            if (!extension.IsNullOrEmpty())
            {
                if (String.Compare(extension.ToLower(), ".docx", true) == 0)
                    icon = "word-icon.png";
                else if (String.Compare(extension.ToLower(), ".pdf", true) == 0)
                    icon = "pdf-icon.png";
            }
            return String.Format("/Content/Images/{0}", icon);            
        }

        /// <summary>
        /// Creates a Job Details link for a job
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="jobID"></param>
        /// <param name="jobUrlName"></param>
        /// <returns></returns>
        public static String JobDetailsUrl(this UrlHelper helper, int jobID, String jobUrlName, String companyKey = null, bool includeDomainAddress = false)
        {
            String domain = includeDomainAddress ? WebUtil.GetDomainAddress() : String.Empty;
            if(companyKey.IsEmpty())
                return String.Format("{0}/job/details/{1}/{2}", domain, jobID, jobUrlName);

            return String.Format("{0}/{1}/{2}/{3}", domain, companyKey, jobID, jobUrlName);
        }
        /// <summary>
        /// Creates a Product Details Link according to product info
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="productID"></param>
        /// <param name="productUrl"></param>
        /// <param name="linkText"></param>
        /// <returns></returns>
        public static MvcHtmlString ProductDetailsLink(this HtmlHelper helper, int productID, String productUrl, String linkText)
        {
            return new MvcHtmlString(String.Format("<a href=\"/product/details/{0}/{1}\">{2}</a>", productID, productUrl, linkText));
        }

        /// <summary>
        /// Creates Company Address Html to Show in the Company Profile Page
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="address"></param>
        /// <param name="district"></param>
        /// <param name="country"></param>
        /// <param name="phone"></param>
        /// <param name="fax"></param>
        /// <param name="email"></param>
        /// <param name="web"></param>
        /// <returns></returns>
        public static MvcHtmlString BuildCompanyAddress(this HtmlHelper helper, String address, String district, String country, String phone, String fax, String email, String web)
        {
            StringBuilder sb = new StringBuilder(10);
            sb.AppendFormat("{0}", address.HtmlEncode());
            sb.AppendFormat("{0}{1}, {2}", address.IsEmpty() ? String.Empty : "<br/>", district.HtmlEncode(), country.HtmlEncode());
            if(!phone.IsEmpty())
                sb.AppendFormat("<br />Phone: {0}", phone.HtmlEncode());
            if (!fax.IsEmpty())
                sb.AppendFormat("Fax: {0}", phone.IsEmpty() ? "<br/>" : ", ", fax.HtmlEncode());
            if (!email.IsEmpty())
                sb.AppendFormat("<br />Email: {0}", email.HtmlEncode());
            if (!web.IsEmpty())
                sb.AppendFormat("<br/>Web Site: <a href='{0}' target='_blank'>{0}</a>", WebUtil.GetCompleteUrl(web));

            return MvcHtmlString.Create(sb.ToString());
        }

        #region Private Methods
        
        public static string GetCategoryListLink(String categoryName)
        {
            return String.Format("/product/category/{0}", categoryName.ToSeoUrl());
        }
        /// <summary>
        /// Gets Formated Data for Display Purpose
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static String FormatData(this HtmlHelper helper, object data)
        {
            return WebUtil.FormatData(data);
        }

        /// <summary>
        /// Gets Resume Download Url
        /// </summary>
        /// <param name="jobSeekerID"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static String ResumeDownloadUrl(this UrlHelper url, int resumeID)
        {
            //return String.Format("{0}/{1}/{2}", AppConstants.Directories.RESUMES, jobSeekerID, fileName);
            return String.Format("{0}/{1}", url.PublicUrl("DownloadResume", "FileDownload"), resumeID);
        }
        
        /// <summary>
        /// Creates Category Breadcrumb for a Given Category ID
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="categoryID"></param>
        /// <param name="buildLink"></param>
        /// <returns></returns>
        public static MvcHtmlString GetCategoryBreadCrumb(this HtmlHelper helper, int categoryID, bool buildLink = false)
        {
            if (categoryID > 0)
            {                
                CategoryViewModel category = ApplicationCache.Categories.FirstOrDefault(P => P.ID == categoryID);
                if (category != null)
                {
                    List<String> names = new List<String>();
                    names.Add(category.Name);
                    while (category.ParentCategory != null)
                    {
                        names.Add(category.ParentCategory.Name);
                        category = category.ParentCategory;
                    }
                    StringBuilder sb = new StringBuilder(10);
                    for (int i = names.Count - 1; i >= 0; i--)
                    {
                        String format = " -> {0}";
                        if (sb.Length == 0)
                            format = "{0}";

                        sb.AppendFormat(format, buildLink ?
                            helper.ActionLink(names[i], "category", "job", new { area = AppConstants.Area.PUBLIC, id = names[i].ToSeoUrl() }, null).ToHtmlString()
                            : names[i]);
                    }
                    return MvcHtmlString.Create(sb.ToString());
                }
            }
            return null;
        }

        public static MvcHtmlString SelectableCategoryList(this HtmlHelper helper, List<Jb.Web.ViewModels.CategoryViewModel> categories, bool addSelectionRadioForAllParents, int selectedCategory = 0, bool includeChildCategories = true)
        {
            if (categories == null || categories.Count == 0)
                return null;
            StringBuilder sb = new StringBuilder();
            List<CategoryViewModel> parentCategories = (from P in categories where P.ParentID == null select P).ToList();
            int rowCounter = 0;
            bool hasColumnClosed = true;
            foreach (CategoryViewModel parentCategory in parentCategories)
            {
                if (rowCounter > 0 && rowCounter % ConfigReader.NumberOfRowsInCategorySelection == 0)
                {
                    sb.Append("</div>");
                    hasColumnClosed = true;
                    rowCounter = 0;
                }
                if (rowCounter == 0)
                {
                    sb.AppendFormat("<div class='category-column'><div class='parent-category' style='margin-top:0px;'>");
                    hasColumnClosed = false;
                }
                else
                    sb.Append("<div class='parent-category'>");
                if (addSelectionRadioForAllParents)
                {
                    if (selectedCategory == parentCategory.ID)
                        sb.AppendFormat("<input checked='checked' name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/> <label for='rdnCategory_{0}'>{1}</label>", parentCategory.ID, parentCategory.Name);
                    else
                        sb.AppendFormat("<input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/> <label for='rdnCategory_{0}'>{1}</label>", parentCategory.ID, parentCategory.Name);
                    //sb.AppendFormat();
                }
                else
                    sb.AppendFormat("{0}", parentCategory.Name);
                sb.Append("</div>");
                rowCounter++;
                if (rowCounter % ConfigReader.NumberOfRowsInCategorySelection == 0)
                {
                    sb.Append("</div>");
                    hasColumnClosed = true;
                    rowCounter = 0;
                }
                //var firstLevelChildren = from P in ApplicationCache.Categories where P.ParentID == parentCategory.ID && P.PropertyDefinition.IsNullOrEmpty() select P;
                //foreach (CategoryViewModel firstLevelChild in firstLevelChildren)
                //{
                    //if (rowCounter > 0 && rowCounter % ConfigReader.NumberOfRowsInCategorySelection == 0)
                    //{
                    //    sb.Append("</div>");
                    //    hasColumnClosed = true;
                    //    rowCounter = 0;
                    //}
                    //if (rowCounter == 0)
                    //{
                    //    sb.AppendFormat("<div class='category-column'><div class='first-child'>");
                    //    hasColumnClosed = false;
                    //}
                    //else
                    //    sb.Append("<div class='first-child'>");
                    //if (addSelectionRadioForAllParents)
                    //{
                    //    if (selectedCategory == firstLevelChild.ID)
                    //        sb.AppendFormat("<input checked='checked' name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/><label for='rdnCategory_{0}'>{1}</label>", firstLevelChild.ID, firstLevelChild.Name);
                    //    else
                    //        sb.AppendFormat("<input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/><label for='rdnCategory_{0}'>{1}</label>", firstLevelChild.ID, firstLevelChild.Name);
                    //}
                    //else
                    //    sb.AppendFormat("{0}", firstLevelChild.Name);
                    //sb.Append("</div>");
                    //rowCounter++;
                    //if (rowCounter % ConfigReader.NumberOfRowsInCategorySelection == 0)
                    //{
                    //    sb.Append("</div>");
                    //    hasColumnClosed = true;
                    //    rowCounter = 0;
                    //}
                    var secondLevelChildren = from P in ApplicationCache.Categories where P.ParentID == parentCategory.ID select P;
                    //if (!addSelectionRadioForAllParents)
                    if(includeChildCategories)
                    {
                        foreach (CategoryViewModel secondLevelChild in secondLevelChildren)
                        {
                            if (rowCounter == 0)
                            {
                                sb.AppendFormat("<div class='category-column'>");
                                hasColumnClosed = false;
                            }
                            sb.AppendFormat("<div class='jb-second-child'>");
                            ///Product Cannot be entered under an empty category definition
                            //if (secondLevelChild.PropertyDefinition.IsNullOrEmpty())
                            //    sb.AppendFormat(secondLevelChild.Name);
                            if (selectedCategory == secondLevelChild.ID)
                                sb.AppendFormat("<input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}' checked='checked'/> <label for='rdnCategory_{0}'>{1}</label>", secondLevelChild.ID, secondLevelChild.Name);
                            else
                                sb.AppendFormat("<input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/> <label for='rdnCategory_{0}'>{1}</label>", secondLevelChild.ID, secondLevelChild.Name);
                            sb.Append("</div>");
                            rowCounter++;
                            if (rowCounter % ConfigReader.NumberOfRowsInCategorySelection == 0)
                            {
                                sb.Append("</div>");
                                hasColumnClosed = true;
                                rowCounter = 0;
                            }
                        }
                    }
                //}
            }
            if (!hasColumnClosed)
                sb.Append("</div>");
            return new MvcHtmlString(sb.ToString());
        }      

        #endregion Private Methods

        #region ViewData Extensions
        /// <summary>
        /// An extension to viewdata to determine whether there is any data saved notification or not
        /// </summary>
        /// <param name="viewData"></param>
        /// <returns></returns>
        public static bool HasSaved(this ViewDataDictionary viewData)
        {
            return viewData[AppConstants.ViewDataKeys.SAVED] == null ? false : Jb.Common.DB.NullHandler.GetBoolean(viewData[AppConstants.ViewDataKeys.SAVED]);
        }
        #endregion
    }
}